<template>
  <el-dialog :title="title" :visible.sync="dialogVisible" :close-on-click-modal="false" :width="width" @close="close('ruleForm')">
    <el-form
      v-if="dialogVisible"
      class="dialog-form"
      ref="ruleForm"
      :model="ruleForm"
      :label-width="labelWidth"
      :label-position="labelPosition"
    >
      <el-form-item
        v-for="(item, index) in options"
        :key="'form_' + index"
        :label="item.title"
        :prop="item.field"
        :rules="item.rules"
      >
        <slot :name="item.slot" v-if="item.hasOwnProperty('slot') && item.slot" :slotProps="item"></slot>
        <template v-else>
          <!-- el-input -->
          <template v-if="item.type === 'input'">
            <span v-if="['view'].includes(mode)">
              {{
              ruleForm[item.field]
              }}
            </span>
            <el-input
              v-else
              v-model="ruleForm[item.field]"
              clearable
              :placeholder="item.placeholder"
              type="text"
              :size="item.size || 'middle'"
              :maxlength="item.maxlength"
              :show-word-limit="item.showWordLimit || false"
              :disabled="item.disabled || false"
              :readonly="false || false"
              :style="{ width: item.width + 'px' }"
              @blur="(e) => handleChange(item.field, 'input', e)"
            ></el-input>
          </template>

          <!-- el-input-number -->
          <template v-else-if="item.type === 'input-number'">
            <span v-if="['view'].includes(mode)">
              {{
              ruleForm[item.field]
              }}
            </span>
            <el-input-number
              v-model="ruleForm[item.field]"
              clearable
              :placeholder="item.placeholder"
              :size="item.size || 'middle'"
              :controls="item.controls"
              :min="item.min"
              :max="item.max"
              :step="item.step"
              :precision="item.precision"
              :disabled="item.disabled || false"
              :readonly="false || false"
              :style="{ width: item.width + 'px', 'text-align': 'left' }"
              @blur="(e) => handleChange(item.field, 'number', e)"
            ></el-input-number>
          </template>
          <!-- el-select -->
          <template v-else-if="item.type === 'select'">
            <span v-if="['view'].includes(mode)">
              {{
              item.options
              ? item.options.find(
              (ii) =>
              ii[item.optionValue || "value"] == ruleForm[item.field]
              )
              ? item.options.find(
              (ii) =>
              ii[item.optionValue || "value"] == ruleForm[item.field]
              )[item.optionKey || "label"]
              : ""
              : ""
              }}
            </span>
            <el-select
              v-else
              v-model="ruleForm[item.field]"
              clearable
              :placeholder="item.placeholder"
              :size="item.size || 'middle'"
              :disabled="item.disabled || false"
              :readonly="false || false"
              :style="{ width: item.width + 'px' }"
              @change="(e) => handleChange(item.field, 'select', e)"
            >
              <el-option
                :label="row[item.optionKey] || row.label"
                :value="row[item.optionValue] || row.value"
                v-for="row in item.options"
                :key="row[item.optionValue]"
              ></el-option>
            </el-select>
          </template>

          <template v-else-if="item.type === 'cascader'">
            <span v-if="['view'].includes(mode)">
              {{
              item.labels
              ? item.labels.map((ii) => ruleForm[ii]).join(item.separator)
              : ""
              }}
            </span>
            <el-cascader
              v-else
              :options="item.options"
              :props="item.props"
              clearable
              :size="item.size || 'middle'"
              :placeholder="item.placeholder"
              :disabled="item.disabled || false"
              :show-all-levels="item.showAllLevels"
              :separator="item.separator"
              v-model="ruleForm[item.field]"
              @change="(e) => handleChange(item.field, 'cascader', e)"
            ></el-cascader>
          </template>

          <!-- el-date-picker -->
          <template v-else-if="item.type === 'date'">
            <span v-if="['view'].includes(mode)">
              {{
              ruleForm[item.field]
              }}
            </span>
            <el-date-picker
              v-else
              :type="item.dateType"
              v-model="ruleForm[item.field]"
              clearable
              :placeholder="item.placeholder"
              :range-separator="item.rangeSeparator"
              :size="item.size || 'middle'"
              :disabled="item.disabled || false"
              :readonly="false || false"
              :style="{ width: item.width + 'px' }"
              :format="item.format || 'yyyy-MM-DD '"
              :value-format="item.format || 'yyyy-MM-DD '"
              @change="(e) => handleChange(item.field, 'date', e)"
            ></el-date-picker>
          </template>

          <!-- el-time-picker -->
          <template v-else-if="item.type === 'time'">
            <span v-if="['view'].includes(mode)">
              {{
              ruleForm[item.field]
              }}
            </span>
            <el-time-picker
              v-else
              v-model="ruleForm[item.field]"
              clearable
              :placeholder="item.placeholder"
              :size="item.size || 'middle'"
              :disabled="item.disabled || false"
              :readonly="false || false"
              :style="{ width: item.width + 'px' }"
              :format="item.format || 'hh:mm:ss'"
              :value-format="item.format || 'hh:mm:ss'"
              @change="(e) => handleChange(item.field, 'time', e)"
            ></el-time-picker>
          </template>

          <!-- el-switch -->
          <template v-else-if="item.type === 'switch'">
            <span v-if="['view'].includes(mode)">
              {{
              ruleForm[item.field] === item.activeValue
              ? item.activeText || "开启"
              : item.inactiveText || "关闭"
              }}
            </span>
            <el-switch
              v-else
              v-model="ruleForm[item.field]"
              clearable
              :placeholder="item.placeholder"
              :disabled="item.disabled || false"
              :active-text="item.activeText"
              :inactive-text="item.inactiveText"
              :active-value="item.activeValue"
              :inactive-value="item.inactiveValue"
              :active-color="item.activeColor"
              :inactive-color="item.inactiveColor"
              :validate-event="true"
              @change="(e) => handleChange(item.field, 'switch', e)"
            ></el-switch>
          </template>

          <!-- el-checkbox -->
          <template v-else-if="item.type === 'checkbox'">
            <span v-if="['view'].includes(mode)">
              {{
              item.options
              ? item.options
              .map((ii) =>
              ii[item.optionValue || "value"] === ruleForm[item.field]
              ? ii[item.optionKey || "label"]
              : ""
              )
              .join("/")
              : ""
              }}
            </span>
            <el-checkbox-group
              v-else
              v-model="ruleForm[item.field]"
              clearable
              :disabled="item.disabled || false"
              @change="(e) => handleChange(item.field, 'checkbox', e)"
            >
              <el-checkbox
                v-for="row in item.options"
                :key="row[item.optionValue || 'value']"
                :label="row[item.optionValue || 'value']"
                :name="row[item.optionValue || 'value']"
              >{{ row[item.optionLabel || "label"] }}</el-checkbox>
            </el-checkbox-group>
          </template>

          <!-- el-radio -->
          <template v-else-if="item.type === 'radio'">
            <span v-if="['view'].includes(mode)">
              {{
              item.options
              ? item.options.find(
              (ii) =>
              ii[item.optionValue || "value"] === ruleForm[item.field]
              )[item.optionKey || "label"]
              : ""
              }}
            </span>

            <el-radio-group
              v-else
              v-model="ruleForm[item.field]"
              :disabled="item.disabled || false"
              @change="(e) => handleChange(item.field, 'radio', e)"
            >
              <el-radio
                v-for="row in item.options"
                :key="row[item.optionValue || 'value']"
                :label="row[item.optionValue || 'value']"
              >{{ row[item.optionKey || "label"] }}</el-radio>
            </el-radio-group>
          </template>

          <!-- el-textarea -->
          <template v-else-if="item.type === 'textarea'">
            <span v-if="['view'].includes(mode)">
              {{
              ruleForm[item.field]
              }}
            </span>
            <el-input
              v-else
              v-model="ruleForm[item.field]"
              clearable
              :placeholder="item.placeholder"
              type="textarea"
              :maxlength="item.maxlength"
              :disabled="item.disabled || false"
              :readonly="false || false"
              :show-word-limit="true"
              :rows="item.rows||4"
              :style="{ width: item.width + 'px' }"
              @blur="(e) => handleChange(item.field, 'textarea', e)"
            ></el-input>
          </template>

          <!-- el-upload -->
          <template v-else-if="item.type === 'upload'">
            <TheUpload
              :disabled="item.disabled || item.mode == 'view'"
              :files="ruleForm[item.field]"
              :limit="item.maxlength"
              :type="item.fileType || 'picture-card'"
              :accept="item.accept||'.jpg,.png,.jpeg'"
              :thumbnail="item.thumbnail"
              @upload="(e) => onUpload(e, item.field)"
            />
          </template>
        </template>
      </el-form-item>
      <div class="tip" v-if="tip">{{ tip }}</div>
    </el-form>
    <slot name="footer" v-if="slotFooter"></slot>
    <span slot="footer" v-else class="dialog-footer">
      <el-button @click="resetForm('ruleForm')" v-if="mode !== 'view'">重 置</el-button>
      <el-button type="primary" @click="submitForm('ruleForm')" v-if="mode !== 'view'">确 定</el-button>
      <el-button type="primary" @click="close" v-if="mode === 'view'">关 闭</el-button>
    </span>
  </el-dialog>
</template>

<script>
import TheUpload from "@/components/TheUpload";
export default {
  components: { TheUpload },
  props: {
    slotFooter: {
      type: Boolean,
      default: false
    },
    width: {
      type: String,
      default: "500px"
    },
    labelWidth: {
      type: String,
      default: "auto"
    },
    mode: {
      type: String,
      default: "create"
    },
    title: {
      type: String,
      default: ""
    },
    labelPosition: {
      type: String,
      default: "left"
    },
    tip: {
      type: String,
      default: ""
    },
    options: {
      type: Array,
      default: () => [
        {
          type: "upload",
          prop: "upload",
          title: "upload",
          default: [
            {
              url:
                "https://hqmimage.oss-cn-beijing.aliyuncs.com/b930c622947940de9fc007dbe6028543.jpg"
            }
          ],
          disabled: false,
          maxlength: 12
        },
        {
          type: "input",
          prop: "input",
          title: "ElInput",
          placeholder: "ElInput",
          default: "input",
          size: "large",
          maxlength: 12,
          disabled: false,
          readonly: false,
          width: 270,
          slot: "slotName" //自定义组件插槽名，覆盖默认组件
        },
        {
          type: "input-number",
          prop: "input1",
          title: "ElInput-number",
          placeholder: "ElInput-number",
          default: 1,
          size: "large",
          max: 1,
          min: 0,
          step: 1,
          precision: 2,
          controls: false,
          disabled: false,
          readonly: false,
          width: 270
        },
        {
          type: "select",
          prop: "select",
          title: "ElSelect",
          placeholder: "ElSelect",
          default: "ElSelect",
          size: "large",
          options: [],
          optionKey: "label",
          optionValue: "value",
          disabled: false,
          readonly: false,
          width: 270
        },
        {
          type: "date",
          prop: "date",
          title: "date",
          placeholder: "date",
          default: "",
          size: "large",
          disabled: false,
          width: 270
        },
        {
          type: "time",
          prop: "time",
          title: "time",
          placeholder: "time",
          default: "",
          size: "large",
          disabled: false,
          width: 270
        },
        // {
        //   type: "checkbox",
        //   prop: "checkbox",
        //   title: "checkbox",
        //   default: [1],
        //   options: [{ label: 1, value: 1 }],
        //   optionKey: "label",
        //   optionValue: "q11",
        //   disabled: false,
        //   width: 270
        // },
        {
          type: "radio",
          prop: "radio",
          title: "radio",
          default: 1,
          options: [{ label: 1, value: 1 }],
          optionKey: "label",
          optionValue: "value",
          disabled: false,
          width: 270
        },

        {
          type: "textarea",
          prop: "textarea",
          title: "ElInput",
          placeholder: "ElInput",
          default: "input",
          size: "large",
          maxlength: 1,
          disabled: false,
          readonly: false,
          width: 270
        }
      ]
    },
    form: {
      type: Object,
      default: () => {}
    },
    api: {
      type: Function,
      default: () => {
        return () => {};
      }
    },
    autoClose: {
      type: Boolean,
      default: true
    },
    renderFunc: {
      //特殊接口返回数据返回格式化，配合autoPlay：false 使用
      type: Function,
      default: null
    }
  },
  watch: {
    ruleForm: {
      deep: true,
      immediate: true,
      handler: function(newV, oldV) {
        console.log(newV, "this");
        this.$emit("update:form", newV);
      }
    }
  },
  data() {
    return {
      dialogVisible: false,
      ruleForm: {},
      ruleFormCopy: {}
    };
  },
  created() {},
  mounted() {
    this.init();
  },
  methods: {
    submitForm(formName) {
      console.log(this.form, "submitForm");
      this.$refs[formName].validate(valid => {
        if (valid) {
          this.$emit("submit", this.ruleForm);
          if (this.autoClose) {
            this.close("ruleForm");
          }
        } else {
          console.log("error submit!!");
          return false;
        }
      });
    },
    resetForm(formName) {
      this.$refs["ruleForm"].resetFields();
    },
    close(formName) {
      this.$refs["ruleForm"].resetFields();
      this.dialogVisible = false;
    },
    handleChange(prop, type, e) {},
    async init() {
      for (let i = 0; i < this.options.length; i++) {
        const item = this.options[i];
        if (this.ruleForm.hasOwnProperty(item.field)) {
          throw "form表单prop[" + item.field + "]字段重复";
        }
        this.$set(this.ruleForm, this.options[i].field, "");
        if (
          Object.prototype.hasOwnProperty.call(item, "default") &&
          item.default !== ""
        ) {
          this.$set(
            this.ruleForm,
            this.options[i].field,
            this.options[i].default
          );
        }
        if (
          Object.prototype.hasOwnProperty.call(item, "api") &&
          item.api !== ""
        ) {
          const api = item.api;
          await api({ ...item.params }).then(res => {
            if (res.code === "SUCCESS") {
              item.options = res.data;
            }
          });
        }
      }
      console.log(this.ruleForm, "aaaa");
      this.ruleFormCopy = { ...this.ruleForm };
    },
    async open(row) {
      if (this.mode !== "create") {
        const res = this.api ? await this.api(row) : { data: {} };
        if (this.renderFunc) {
          const result = this.renderFunc(res);
          this.ruleForm = { ...result };
        } else {
          if (this.mode === "view") {
            this.ruleForm = res.data;
          } else {
            for (const key in this.ruleForm) {
              if (Object.hasOwnProperty.call(this.ruleForm, key)) {
                this.$set(
                  this.ruleForm,
                  key,
                  res.data[key] || this.ruleForm[key]
                );
              }
            }
          }
        }
      } else {
        this.ruleForm = { ...this.ruleFormCopy };
      }

      this.dialogVisible = true;
    },
    onUpload(e, field) {
      this.$set(
        this.ruleForm,
        field,
        e.files.map(file => file.url)
      );
    }
  }
};
</script>
<style scoped lang="scss">
::v-deep .el-dialog__body {
  max-height: 600px;
  overflow: auto;
}
::v-deep .el-form {
}
::v-deep .el-input-number .el-input__inner {
  text-align: left !important;
  padding: 15px;
}
.tip {
  text-align: center;
}
</style>
